package com.xc.quickstart.common.interceptor;

import com.alibaba.fastjson.JSON;
import com.xc.quickstart.common.annotation.AvoidDuplicateSubmit;
import com.xc.quickstart.common.constant.RedisKeyConstant;
import com.xc.quickstart.common.context.ApiContext;
import com.xc.quickstart.common.model.ApiResponse;
import com.xc.quickstart.infrastructure.redis.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author dxl
 */
@Slf4j
@Component
public class AvoidDuplicateSubmitInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private RedisService redisService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        if (!judge(handler)) {
            return true;
        }

        String jobNumber = ApiContext.getApiContextModel().getJobNumber();
        if (StringUtils.isEmpty(jobNumber)) {
            return true;
        }

        String redisKey = String.format(RedisKeyConstant.AVOID_DUPLICATE_SUBMIT_KEY, jobNumber, request.getServletPath());
        if (redisService.exists(redisKey)) {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            response.getWriter().print(JSON.toJSONString(ApiResponse.fail("提交太频繁,请稍后再试")));
            response.getWriter().close();
            return false;
        }

        Method method = ((HandlerMethod) handler).getMethod();
        AvoidDuplicateSubmit annotation = method.getAnnotation(AvoidDuplicateSubmit.class);
        redisService.setex(redisKey, JSON.toJSONString(request.getServletPath()), annotation.seconds(), TimeUnit.SECONDS);

        return true;
    }

    private boolean judge(Object handler) {
        if (!(handler instanceof HandlerMethod)) {
            return false;
        }

        Method method = ((HandlerMethod) handler).getMethod();

        AvoidDuplicateSubmit annotation = method.getAnnotation(AvoidDuplicateSubmit.class);
        if (Objects.isNull(annotation)) {
            return false;
        }

        return true;
    }

}
